#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
# new Env("蓝氏宠物")
# cron: 0 9 * * *
✦ 小程序信息    ▸ 名称：蓝氏宠物LEGENDSANDY
▸ 类别：积分换实物
▸ 可换种类：宠物类
✦ 执行说明    ▸ 首次执行需手动进入小程序完成手机号绑定
▸ 每日自动执行签到任务
✦ 环境变量    ▸ Applet_LSCW_Wxid: 指定允许执行的账号(Wxid)，多个用英文逗号分隔
"""
import time
import json
import random
import os
import urllib3
from typing import Optional, Dict, Any

# 确保requests库已安装
try:
    import requests
    from requests.exceptions import RequestException
except ImportError:
    print("错误: 需要安装 requests 库，请执行: pip install requests")
    exit(1)

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

# 环境变量配置
LOCAL_PROXY = os.getenv("API_PROXY")  # 直接使用环境变量值，不添加"http://"

class LanshiSignin:
    """蓝氏宠物小程序签到类"""
    def __init__(self):
        """初始化签到客户端"""
        self.base_url = "https://api.vshop.hchiv.cn"
        self.app_id = "wxb7a9c0dd9a2fcc53"
        self.session = requests.Session()
        self.session.verify = False  # 禁用SSL验证
        self.headers = {
            "Host": "api.vshop.hchiv.cn",
            "Connection": "keep-alive",
            "content-type": "application/json",
            "Accept-Encoding": "gzip,compress,br,deflate",
            "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.61(0x18003d2a) NetType/WIFI Language/zh_CN",
            "Referer": "https://servicewechat.com/wxb7a9c0dd9a2fcc53/30/page-frame.html"
        }
        self.activity_id: Optional[str] = None
        self.client_token: Optional[str] = None

    def get_wx_list(self):
        """获取微信账户列表"""
        try:
            if not LOCAL_PROXY:
                print("⚠️ 未配置API_PROXY环境变量")
                return []
                
            base_url = LOCAL_PROXY if LOCAL_PROXY.startswith(('http://', 'https://')) else f"http://{LOCAL_PROXY}"
            url = f"{base_url.rstrip('/')}/getallwx"
            
            print(f"尝试连接协议服务: {url}")
            response = requests.get(url, timeout=15, verify=False)
            
            if response.status_code == 200:
                return response.json()
            print(f"获取微信列表失败: HTTP {response.status_code}")
        except RequestException as e:
            print(f"获取微信列表失败: {str(e)}")
        return []

    def get_wx_code(self, wxid):
        """获取小程序登录凭证"""
        try:
            if not LOCAL_PROXY:
                print("⚠️ 未配置API_PROXY环境变量")
                return None
                
            base_url = LOCAL_PROXY if LOCAL_PROXY.startswith(('http://', 'https://')) else f"http://{LOCAL_PROXY}"
            url = f"{base_url.rstrip('/')}/loginbyapp?Wxid={wxid}&appid={self.app_id}"
            
            print(f"获取登录Code: {url}")
            response = requests.get(url, timeout=15, verify=False)
            
            if response.status_code == 200:
                data = response.json()
                if data.get("code"):
                    return data["code"]
                print("响应中未找到code字段")
            print(f"获取wxCode失败: HTTP {response.status_code}")
        except RequestException as e:
            print(f"获取wxCode异常: {str(e)}")
        return None

    def get_activity_list(self) -> Optional[str]:
        """获取签到活动ID"""
        payload = {
            "appId": self.app_id,
            "openId": True,
            "shopNick": "",
            "interfaceSource": 0,
            "pageNumber": 1,
            "pageSize": 20,
            "decoActStatus": []
        }
        try:
            response = self.session.post(
                f"{self.base_url}/jfmb/cloud/activity/activity/activityList",
                params={
                    "sideType": "3",
                    "appId": self.app_id,
                    "shopNick": self.app_id
                },
                json=payload,
                headers=self.headers
            )
            response.raise_for_status()
            data = response.json()
            if data.get("data", {}).get("code") == 200:
                for activity in data.get("data", {}).get("data", {}).get("dataList", []):
                    if "签到" in activity.get("name", ""):
                        activity_id = str(activity.get("id"))
                        print(f"获取到签到活动: {activity.get('name')} (ID: {activity_id})")
                        return activity_id
                print("未找到包含'签到'的活动")
            else:
                print(f"获取活动列表失败：{data.get('message', '未知错误')}")
        except RequestException as e:
            print(f"获取活动列表请求失败: {e}")
        return None

    def login(self, code: str) -> bool:
        """用户登录"""
        timestamp = int(time.time() * 1000)
        payload = {
            "appId": self.app_id,
            "openId": True,
            "shopNick": "",
            "timestamp": timestamp,
            "interfaceSource": 0,
            "wxInfo": code,
            "extend": json.dumps({
                "sourcePage": "/packageA/pages/integral-index/integral-index",
                "activityId": "",
                "sourceShopId": "",
                "guideNo": "",
                "way": "member",
                "linkType": "2001"
            }),
            "sessionIdForWxShop": ""
        }
        try:
            response = self.session.post(
                f"{self.base_url}/jfmb/cloud/member/wechatlogin/authLoginApplet",
                params={
                    "sideType": "3",
                    "mob": "",
                    "appId": self.app_id,
                    "shopNick": self.app_id,
                    "timestamp": timestamp,
                    "guideNo": ""
                },
                json=payload,
                headers=self.headers
            )
            response.raise_for_status()
            data = response.json()
            if data.get("data", {}).get("code") == 200:
                client_token = data.get("data", {}).get("data", {}).get("clientToken")
                if client_token:
                    self.client_token = client_token
                    self.headers["Authorization"] = f"Bearer {client_token}"
                    print("账号登录成功")
                    return True
            print("账号登录失败，请登录小程序手动签到一次授权手机号后再运行脚本")
        except RequestException as e:
            print(f"登录请求失败: {e}")
        return False

    def get_client_info(self) -> Optional[Dict[str, Any]]:
        """获取账号信息"""
        timestamp = int(time.time() * 1000)
        payload = {
            "appId": self.app_id,
            "openId": True,
            "shopNick": "",
            "timestamp": timestamp,
            "interfaceSource": 0
        }
        try:
            response = self.session.post(
                f"{self.base_url}/jfmb/cloud/member/tblogin/getClientInfo",
                params={
                    "sideType": "3",
                    "shopNick": self.app_id
                },
                json=payload,
                headers=self.headers
            )
            response.raise_for_status()
            data = response.json()
            if data.get("data", {}).get("code") == 200:
                client_data = data.get("data", {}).get("data", {})
                print(f"账号信息获取成功，当前积分: {client_data.get('residualIntegral', '未知')}")
                return client_data
            print(f"获取账号信息失败: {data.get('data', {}).get('message', '未知错误')}")
        except RequestException as e:
            print(f"获取账号信息请求失败: {e}")
        return None

    def submit_signin(self, user_mob: str) -> bool:
        """提交签到"""
        timestamp = int(time.time() * 1000)
        payload = {
            "appId": self.app_id,
            "openId": True,
            "shopNick": "",
            "timestamp": timestamp,
            "interfaceSource": 0,
            "activityId": self.activity_id
        }
        try:
            response = self.session.post(
                f"{self.base_url}/jfmb/api/play-default/sign/add-sign-new.do",
                params={
                    "sideType": "3",
                    "mob": user_mob,
                    "shopNick": self.app_id
                },
                json=payload,
                headers=self.headers
            )
            response.raise_for_status()
            data = response.json()
            if data.get("success"):
                sign_data = data.get("data", {})
                if sign_data.get("message") == "已签到":
                    print("今日已签到")
                    return True
                if sign_data.get("integral"):
                    print(f"签到成功，获得{sign_data['integral']}积分")
                    return True
            print(f"签到失败: {data.get('message', '未知错误')}")
        except RequestException as e:
            print(f"签到请求失败: {e}")
        return False

    def process_account(self, nick_name: str, code: str) -> bool:
        """
        处理单个账号的签到流程
        Args:
            nick_name (str): 账号昵称
            code (str): 微信小程序登录code
        Returns:
            bool: 是否处理成功
        """
        print(f"\n开始处理账号: {nick_name}")
        
        # 1. 登录
        if not self.login(code):
            print(f"账号 {nick_name} 登录失败")
            return False
            
        # 2. 获取账号信息
        client_info = self.get_client_info()
        if not client_info:
            print(f"账号 {nick_name} 获取信息失败")
            return False
            
        user_mob = client_info.get("user_mob")
        if not user_mob:
            print(f"账号 {nick_name} 未获取到手机号")
            return False
            
        # 3. 提交签到
        if not self.submit_signin(user_mob):
            print(f"账号 {nick_name} 签到失败")
            return False
            
        # 4. 获取最新积分
        self.get_client_info()
        return True

def main():
    """主函数"""
    print("="*50)
    print("蓝氏宠物签到脚本 - 完整修复版")
    print(f"当前时间: {time.strftime('%Y-%m-%d %H:%M:%S')}")
    print("="*50)
    
    # 检查依赖
    try:
        import requests
    except ImportError:
        print("❌ 错误: 需要安装 requests 库")
        print("请执行: pip install requests")
        return
    
    if not LOCAL_PROXY:
        print("❌ 错误: 未检测到API_PROXY环境变量")
        print("请设置环境变量: export API_PROXY='你的协议服务IP:端口'")
        print("示例: export API_PROXY='192.168.0.183:5000'")
        return
    
    try:
        signin = LanshiSignin()
        
        # 1. 获取活动ID
        print("\n[1/4] 正在获取签到活动ID...")
        activity_id = signin.get_activity_list()
        if not activity_id:
            print("❌ 获取签到活动ID失败，脚本退出")
            return
        signin.activity_id = activity_id
        
        # 2. 获取微信账号列表
        print("\n[2/4] 正在获取微信账户列表...")
        wx_accounts = signin.get_wx_list()
        if not wx_accounts:
            print("❌ 未获取到任何在线账号")
            print("可能原因:")
            print(f"1. 协议服务不可达 (当前配置: {LOCAL_PROXY})")
            print("2. 协议服务未正常运行")
            print("3. 网络连接问题")
            return
            
        print(f"✅ 获取到 {len(wx_accounts)} 个账号")
        
        # 3. 根据环境变量过滤账号
        allowed_wxids = [x.strip() for x in os.getenv("Applet_LSCW_Wxid", "").split(",") if x.strip()]
        if allowed_wxids:
            print(f"允许的Wxid: {', '.join(allowed_wxids)}")
            filtered_accounts = [acc for acc in wx_accounts if acc.get("Wxid") in allowed_wxids]
            print(f"根据Applet_LSCW_Wxid过滤后，需要处理 {len(filtered_accounts)} 个账号")
        else:
            filtered_accounts = wx_accounts
            print("未设置Applet_LSCW_Wxid环境变量，处理所有账号")
        
        if not filtered_accounts:
            print("❌ 没有符合条件的账号需要处理")
            return
        
        # 4. 处理每个账号
        print("\n[3/4] 开始处理账号...")
        for i, account in enumerate(filtered_accounts, 1):
            wxid = account.get("Wxid")
            wxname = account.get("wxname", f"账号{i}")
            
            print(f"\n{'='*30}")
            print(f"处理账号 {i}/{len(filtered_accounts)}: {wxname} (Wxid: {wxid})")
            print(f"{'='*30}")
            
            code = signin.get_wx_code(wxid)
            if not code:
                print(f"⚠️ 跳过 {wxname} - 获取登录Code失败")
                continue
                
            try:
                if signin.process_account(wxname, code):
                    print(f"✅ {wxname} 处理成功")
                else:
                    print(f"⚠️ {wxname} 处理失败")
            except Exception as e:
                print(f"❌ {wxname} 处理异常: {e}")
                
            if i < len(filtered_accounts):
                wait_time = random.randint(2, 5)
                print(f"等待{wait_time}秒后继续...")
                time.sleep(wait_time)
        
        print("\n[4/4] 所有账号处理完成")
        print(f"\n执行完成 @ {time.strftime('%Y-%m-%d %H:%M:%S')}")
        
    except Exception as e:
        print(f"\n❌ 脚本执行失败: {e}")
    finally:
        print("\n" + "="*50)

if __name__ == "__main__":
    main()